package com.ideaaedi.springcloud.jd.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ideaaedi.springcloud.jd.commonds.constant.BaseConstant;
import com.ideaaedi.springcloud.jd.commonds.entity.BaseCodeMsgEnum;
import com.ideaaedi.springcloud.jd.commonds.entity.PageInfo;
import com.ideaaedi.springcloud.jd.commonds.entity.user.po.SysDictTypePO;
import com.ideaaedi.springcloud.jd.commonds.entity.user.vo.req.SysDictTypeAddReqVO;
import com.ideaaedi.springcloud.jd.commonds.entity.user.vo.req.SysDictTypeListReqVO;
import com.ideaaedi.springcloud.jd.commonds.entity.user.vo.req.SysDictTypeUpdateReqVO;
import com.ideaaedi.springcloud.jd.commonds.entity.user.vo.resp.SysDictTypeDetailRespVO;
import com.ideaaedi.springcloud.jd.commonds.entity.user.vo.resp.SysDictTypeListRespVO;
import com.ideaaedi.springcloud.jd.commonds.exception.BaseException;
import com.ideaaedi.springcloud.jd.commonspring.mapper.SysDictTypeMapper;
import com.ideaaedi.springcloud.jd.commonspring.mybatisplus.ServiceImplExt;
import com.ideaaedi.springcloud.jd.commonspring.mybatisplus.tenant.TenantProvider;
import com.ideaaedi.springcloud.jd.commonspring.validator.ValidId;
import com.ideaaedi.springcloud.jd.user.service.SysDictTypeService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 系统-数据字典类别 服务实现类
 * </p>
 *
 * @author <font size = "20" color = "#3CAA3C"><a href="https://gitee.com/JustryDeng">JustryDeng</a></font> <img src="https://gitee.com/JustryDeng/shared-files/raw/master/JustryDeng/avatar.jpg" />
 * @since 2021.0.1.A
 */
@Service
public class SysDictTypeServiceImpl extends ServiceImplExt<SysDictTypeMapper, SysDictTypePO> implements SysDictTypeService {

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SysDictTypeDetailRespVO add(SysDictTypeAddReqVO req) {
        String code = req.getCode();
        if (code != null) {
            boolean codeUsed = TenantProvider.execGlobal(() -> getOne(new LambdaQueryWrapper<SysDictTypePO>()
                    .select(SysDictTypePO::getId)
                    .eq(SysDictTypePO::getCode, code)
            ) != null)  ;
            if (codeUsed) {
                throw new BaseException(BaseCodeMsgEnum.CODE_BEEN_OCCUPIED, code);
            }
        }
        SysDictTypePO po = new SysDictTypePO();
        BeanUtils.copyProperties(req, po);
        po.setId(null);
        save(po);
        Integer generateId = po.getId();
        // 自动生成的id, 不能为系统id保留值
        boolean needUpdateId = generateId <= BaseConstant.SYS_INTERNAL_DATA_ID_EQ;
        Integer id;
        if (needUpdateId) {
            id = (int)(BaseConstant.SYS_INTERNAL_DATA_ID_EQ + 1);
            update(new SysDictTypePO(), new LambdaUpdateWrapper<SysDictTypePO>()
                    .set(SysDictTypePO::getId, id)
                    .eq(SysDictTypePO::getId, generateId)
            );
        } else {
            id = generateId;
        }
        return detail(id);
    }
    
    @Override
    @ValidId
    @Transactional(rollbackFor = Exception.class)
    public SysDictTypeDetailRespVO delete(Integer id) {
        Objects.requireNonNull(id, "id cannot be null.");
        SysDictTypeDetailRespVO resp = detail(id);
        update(new SysDictTypePO(), new LambdaUpdateWrapper<SysDictTypePO>()
                .set(SysDictTypePO::getDeleted, 1)
                .set(SysDictTypePO::getDeletedTime, System.currentTimeMillis() / 1000)
                .eq(SysDictTypePO::getId, id)
        );
        return resp;
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public SysDictTypeDetailRespVO update(SysDictTypeUpdateReqVO req) {
        Integer id = req.getId();
        Objects.requireNonNull(id, "id cannot be null.");
        String code = req.getCode();
        if (code != null) {
            boolean codeUsed = TenantProvider.execGlobal(() -> getOne(new LambdaQueryWrapper<SysDictTypePO>()
                    .select(SysDictTypePO::getId)
                    .eq(SysDictTypePO::getCode, code)
                    .ne(SysDictTypePO::getId, id)
            ) != null)  ;
            if (codeUsed) {
                throw new BaseException(BaseCodeMsgEnum.CODE_BEEN_OCCUPIED, code);
            }
        }
        // mybatis-plus默认的updateById方法，更新策略默认是NOT_NULL（即更新数据时数据为NULL值时将不更新进数据库）
        SysDictTypePO po = new SysDictTypePO();
        BeanUtils.copyProperties(req, po);
        updateById(po);
        return detail(id);
    }
    
    @Override
    public SysDictTypeDetailRespVO detail(Integer id) {
        Objects.requireNonNull(id, "id cannot be null.");
        SysDictTypePO po = getById(id);
        if (po == null) {
            return null;
        }
        SysDictTypeDetailRespVO resp = new SysDictTypeDetailRespVO();
        BeanUtils.copyProperties(po, resp);
        return resp;
    }
    
    @Override
    public PageInfo<SysDictTypeListRespVO> list(SysDictTypeListReqVO req) {
        int pageNum = req.getPageNum();
        int pageSize = req.getPageSize();
        String dictTypeCode = req.getCode();
        String dictTypeName = req.getName();

        // 分页查
        IPage<SysDictTypePO> pageInfo = new Page<>(pageNum, pageSize);
        IPage<SysDictTypePO> page = this.baseMapper.selectPage(pageInfo,
                new LambdaQueryWrapper<SysDictTypePO>()
            .eq(StringUtils.isNotBlank(dictTypeCode),  SysDictTypePO::getCode, dictTypeCode)
            .like(StringUtils.isNotBlank(dictTypeName),  SysDictTypePO::getName, dictTypeName)
        );
        // 转换为resp模型
        List<SysDictTypePO> records = page.getRecords();
        List<SysDictTypeListRespVO> list;
        if (CollectionUtils.isEmpty(records)) {
            list = Collections.emptyList();
        } else {
            list = records.stream().map(po -> {
                SysDictTypeListRespVO resp = new SysDictTypeListRespVO();
                BeanUtils.copyProperties(po, resp);
                return resp;
            }).collect(Collectors.toList());
        }
        return PageInfo.of(page.getTotal(), pageNum, pageSize, list);
    }
}
